/// @file Integration.cpp
/// @brief performs integration of acceleration to get next velocity and position

#include "Integration.h"

Integration::Integration
                (
                    const IntegrationType _integrationType,
                    const ngl::Real _timestep
                )
{
    m_integrationType = _integrationType;
    m_timestep = _timestep;
}

void Integration::integrateNext(Particle &io_currentParticle)
{
    //calls user-chosen integrator
    switch (m_integrationType)
    {
        case SEMI_IMPLICIT_EULER: { evaluateSemiImplicitEuler(io_currentParticle); break; }
        case LEAPFROG: { evaluateLeapfrog(io_currentParticle); break; }

        default : break;
    }
}

void Integration::evaluateSemiImplicitEuler(Particle &io_currentParticle)
{
    //semi implicit euler from http://en.wikipedia.org/wiki/Semi-implicit_Euler
    io_currentParticle.updateVelocity(io_currentParticle.getVelocity() + (io_currentParticle.getAcceleration() * m_timestep));

    io_currentParticle.updatePosition(io_currentParticle.getPosition() + (io_currentParticle.getVelocity() * m_timestep));
}

void Integration::evaluateLeapfrog(Particle &io_currentParticle)
{
    //modified leapfrog from http://en.wikipedia.org/wiki/Leapfrog_integration
    io_currentParticle.updateVelocity(io_currentParticle.getVelocity() + (((io_currentParticle.getLastAcceleration() + io_currentParticle.getAcceleration()) / 2.0) * m_timestep));

    io_currentParticle.updatePosition(io_currentParticle.getPosition() + (io_currentParticle.getVelocity() * m_timestep) + ((io_currentParticle.getLastAcceleration() / 2.0) * m_timestep * m_timestep));
}

